package vip.pwztx.api.service.impl.song;

import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.symmetric.AES;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.RegExUtils;
import org.springframework.stereotype.Service;
import vip.pwztx.api.constant.Constant;
import vip.pwztx.api.entity.song.Song;
import vip.pwztx.api.result.PageResult;
import vip.pwztx.api.result.ResultCodeEnum;
import vip.pwztx.api.service.song.SongService;

import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 歌曲service实现类
 *
 * @author zhoubaohua
 * @date 2019/10/10
 */
@Service
public class SongServiceImpl implements SongService {

    @Override
    public String getSongDownloadInfo(String platform, String hash, String type, String secret) {
        Map<String, String> headers = new HashMap<String, String>() {{
            put("user-agent", "lx-music request");
            put("content-length", "0");
            put("lxm", secret);
            put("Connection", "close");
            put("accept", "application/json");
            put("host", "tm.tempmusic.tk");
        }};
        return HttpUtil.createGet("http://tm.tempmusic.tk/url/" + platform + "/" + hash + "/" + type).headerMap(headers, true)
                .execute().body();
    }

    @Override
    public PageResult search(String keyword, String platform, Integer page, Integer pageSize) {
        String url = null;
        Map<String, String> headers = new HashMap<>(8);
        switch (platform) {
            case "kg":
                url = String.format(Constant.KG_SONG_SEARCH_URL, keyword, page, pageSize);
                break;
            case "kw":
                url = String.format(Constant.KW_SONG_SEARCH_URL, keyword, page - 1, pageSize);
                break;
            case "tx":
                url = String.format(Constant.TX_SONG_SEARCH_URL, page, pageSize, keyword);
                break;
            case "mg":
                url = String.format(Constant.MG_SONG_SEARCH_URL, keyword, page, pageSize);
                headers.put("osVersion", "android 7.0");
                headers.put("User-Agent", "okhttp/3.9.1");
                break;
            case "wy":
                url = String.format(Constant.WY_SONG_SEARCH_URL, keyword, pageSize * (page - 1), pageSize);
                break;
            default:
                break;
        }
        if (url != null) {
            System.out.println(url);
            String json = HttpUtil.createGet(url).headerMap(headers, true).execute().body();
            PageResult pageResult = new PageResult();
            pageResult.setCode(ResultCodeEnum.SUCCESS.code());
            pageResult.setPageNo(page);
            pageResult.setPageSize(pageSize);
            return getSongList(platform, json, pageResult);
        }
        return PageResult.success(new ArrayList<>(), 0, 0, 0, 0);
    }

    private PageResult getSongList(String platform, String json, PageResult pageResult) {
        List<Song> list = new ArrayList<>();
        JSONObject jsonObject = JSON.parseObject(json);
        switch (platform) {
            case "kg":
                JSONObject data = jsonObject.getJSONObject("data");
                pageResult.setTotal(data.getIntValue("total"));
                data.getJSONArray("info").forEach(item -> {
                    JSONObject info = (JSONObject) item;
                    List<Map<String, Object>> types = new ArrayList<>();
                    if (info.getLongValue("filesize") != 0) {
                        Map<String, Object> type = new HashMap<>(8);
                        type.put("type", "128k");
                        type.put("hash", info.getString("hash"));
                        type.put("size", info.getLongValue("filesize"));
                        type.put("tagType", "success");
                        types.add(type);
                    }
                    if (info.getLongValue("320filesize") != 0) {
                        Map<String, Object> type = new HashMap<>(8);
                        type.put("type", "320k");
                        type.put("hash", info.getString("320hash"));
                        type.put("size", info.getLongValue("320filesize"));
                        type.put("tagType", "warning");
                        types.add(type);
                    }
                    if (info.getLongValue("sqfilesize") != 0) {
                        Map<String, Object> type = new HashMap<>(8);
                        type.put("type", "flac");
                        type.put("hash", info.getString("sqhash"));
                        type.put("size", info.getLongValue("sqfilesize"));
                        type.put("tagType", "danger");
                        types.add(type);
                    }
                    Song song = Song.builder()
                            .copyrightId(info.getString("audio_id"))
                            .albumName(info.getString("album_name"))
                            .songName(info.getString("songname"))
                            .singerName(info.getString("singername"))
                            .fileName(info.getString("filename"))
                            .types(types)
                            .build();
                    list.add(song);
                });
                break;
            case "kw":
                pageResult.setTotal(jsonObject.getIntValue("TOTAL"));
                jsonObject.getJSONArray("abslist").forEach(item -> {
                    JSONObject info = (JSONObject) item;
                    String hash = info.getString("MUSICRID").replace("MUSIC_", "");
                    List<Map<String, Object>> types = new ArrayList<>();
                    info.getString("MINFO");
                    if (info.getString("MINFO").contains("bitrate:128")) {
                        Map<String, Object> type = new HashMap<>(8);
                        type.put("type", "128k");
                        type.put("hash", hash);
                        type.put("tagType", "success");
                        types.add(type);
                    }
                    if (info.getString("MINFO").contains("bitrate:320")) {
                        Map<String, Object> type = new HashMap<>(8);
                        type.put("type", "320k");
                        type.put("hash", hash);
                        type.put("tagType", "warning");
                        types.add(type);
                    }
                    if (info.getString("MINFO").contains("flac")) {
                        Map<String, Object> type = new HashMap<>(8);
                        type.put("type", "flac");
                        type.put("hash", hash);
                        type.put("tagType", "danger");
                        types.add(type);
                    }
                    Song song = Song.builder()
                            .copyrightId(hash)
                            .albumName(info.getString("ALBUM"))
                            .songName(info.getString("SONGNAME"))
                            .singerName(info.getString("ARTIST"))
                            .fileName(info.getString("SONGNAME"))
                            .types(types)
                            .build();
                    list.add(song);
                });
                break;
            case "tx":
                data = jsonObject.getJSONObject("data");
                pageResult.setTotal(data.getJSONObject("song").getIntValue("totalnum"));
                data.getJSONObject("song").getJSONArray("list").forEach(item -> {
                    JSONObject info = (JSONObject) item;
                    List<Map<String, Object>> types = new ArrayList<>();
                    if (info.getLongValue("size128") != 0) {
                        Map<String, Object> type = new HashMap<>(8);
                        type.put("type", "128k");
                        type.put("hash", info.getString("songmid"));
                        type.put("size", info.getLongValue("size128"));
                        type.put("tagType", "success");
                        types.add(type);
                    }
                    if (info.getLongValue("size320") != 0) {
                        Map<String, Object> type = new HashMap<>(8);
                        type.put("type", "320k");
                        type.put("hash", info.getString("songmid"));
                        type.put("size", info.getLongValue("size320"));
                        type.put("tagType", "warning");
                        types.add(type);
                    }
                    if (info.getLongValue("sizeflac") != 0) {
                        Map<String, Object> type = new HashMap<>(8);
                        type.put("type", "flac");
                        type.put("hash", info.getString("songmid"));
                        type.put("size", info.getLongValue("sizeflac"));
                        type.put("tagType", "danger");
                        types.add(type);
                    }
                    JSONArray singers = info.getJSONArray("singer");
                    String singerName = "";
                    if (singers != null && !singers.isEmpty()) {
                        singerName = singers.stream().map(singer -> ((JSONObject) singer).getString("name")).collect(Collectors.joining(","));
                    }
                    Song song = Song.builder()
                            .copyrightId(info.getString("songmid"))
                            .albumName(info.getString("albumname"))
                            .songName(info.getString("songname"))
                            .singerName(singerName)
                            .fileName(info.getString("songname"))
                            .types(types)
                            .build();
                    list.add(song);
                });
                break;
            case "mg":
                data = jsonObject.getJSONObject("songResultData");
                pageResult.setTotal(data.getIntValue("totalCount"));
                data.getJSONArray("result").forEach(item -> {
                    JSONObject info = (JSONObject) item;
                    String hash = info.getString("copyrightId");
                    List<Map<String, Object>> types = new ArrayList<>();
                    JSONArray newRateFormats = info.getJSONArray("newRateFormats");
                    if (newRateFormats != null && !newRateFormats.isEmpty()) {
                        newRateFormats.forEach(format -> {
                            JSONObject formatInfo = (JSONObject) format;
                            if ("PQ".equals(formatInfo.getString("formatType"))) {
                                Map<String, Object> type = new HashMap<>(8);
                                type.put("type", "128k");
                                type.put("hash", hash);
                                type.put("size", formatInfo.getLongValue("androidSize"));
                                type.put("tagType", "success");
                                types.add(type);
                            } else if ("HQ".equals(formatInfo.getString("formatType"))) {
                                Map<String, Object> type = new HashMap<>(8);
                                type.put("type", "320k");
                                type.put("hash", hash);
                                type.put("size", formatInfo.getLongValue("androidSize"));
                                type.put("tagType", "warning");
                                types.add(type);
                            } else if ("ZQ".equals(formatInfo.getString("formatType"))) {
                                Map<String, Object> type = new HashMap<>(8);
                                type.put("type", "flac");
                                type.put("hash", hash);
                                type.put("size", formatInfo.getLongValue("androidSize"));
                                type.put("tagType", "danger");
                                types.add(type);
                            }
                        });
                    }
                    JSONArray albums = info.getJSONArray("albums");
                    String albumName = "";
                    if (albums != null && !albums.isEmpty()) {
                        albumName = albums.stream().map(album -> ((JSONObject) album).getString("name")).collect(Collectors.joining(","));
                    }
                    JSONArray singers = info.getJSONArray("singers");
                    String singerName = "";
                    if (singers != null && !singers.isEmpty()) {
                        singerName = singers.stream().map(singer -> ((JSONObject) singer).getString("name")).collect(Collectors.joining(","));
                    }
                    Song song = Song.builder()
                            .copyrightId(hash)
                            .albumName(albumName)
                            .songName(info.getString("name"))
                            .singerName(singerName)
                            .fileName(info.getString("name"))
                            .types(types)
                            .build();
                    list.add(song);
                });
                break;
            case "wy":
                data = jsonObject.getJSONObject("result");
                pageResult.setTotal(data.getIntValue("songCount"));
                data.getJSONArray("songs").forEach(item -> {
                    JSONObject info = (JSONObject) item;
                    List<Map<String, Object>> types = new ArrayList<>();
                    if (info.getJSONObject("l") != null) {
                        Map<String, Object> type = new HashMap<>(8);
                        type.put("type", info.getLongValue("br"));
                        type.put("hash", info.getLongValue("id"));
                        type.put("tagType", "success");
                        types.add(type);
                    }
                    if (info.getJSONObject("h") != null) {
                        Map<String, Object> type = new HashMap<>(8);
                        type.put("type", info.getLongValue("br"));
                        type.put("hash", info.getLongValue("id"));
                        type.put("tagType", "warning");
                        types.add(type);
                    }
                    if (info.getJSONObject("sq") != null) {
                        Map<String, Object> type = new HashMap<>(8);
                        type.put("type", info.getLongValue("br"));
                        type.put("hash", info.getLongValue("id"));
                        type.put("tagType", "danger");
                        types.add(type);
                    }
                    JSONArray singers = info.getJSONArray("ar");
                    String singerName = "";
                    if (singers != null && !singers.isEmpty()) {
                        singerName = singers.stream().map(singer -> ((JSONObject) singer).getString("name")).collect(Collectors.joining(","));
                    }
                    Song song = Song.builder()
                            .albumName(info.getJSONObject("al").getString("name"))
                            .songName(info.getString("name"))
                            .singerName(singerName)
                            .fileName(info.getString("SONGNAME"))
                            .types(types)
                            .build();
                    list.add(song);
                });
                break;
            default:
                break;
        }
        pageResult.setCurrentSize(list.size());
        pageResult.setData(list);
        return pageResult;
    }
}
